package ms.jasim.model.editor.views;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import ms.jasim.framework.EvaluatorResult;
import ms.jasim.framework.EventSimulator;
import ms.jasim.framework.EventSimulator.SimulatedTreeNode;
import ms.jasim.model.Evaluator;

import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

public class EventSimulationSummaryViewer extends TableViewer {

	private Object[] input;
	private EventSimulationView view;

	class MyContentProvider implements IStructuredContentProvider {

		@Override
		public Object[] getElements(Object inputElement) {
			return input;
		}

		@Override
		public void dispose() {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			// TODO Auto-generated method stub
			
		}
		
	}
	
	class MyLabelProvider extends LabelProvider implements ITableLabelProvider {

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object element, int columnIndex) {
			if (element != null) {
				Object[] o = (Object[]) element;
				EventSimulator sim = (EventSimulator) o[0];
				SimulatedTreeNode best = (SimulatedTreeNode) o[1];
				switch(columnIndex) {
				case 0:
					return sim.getSolution().getName();
				case 1:
					return Float.toString(getScore(sim.getRootNode()));
				case 2:
					return best != null ? Float.toString(getScore(best)) : "-";
				case 3:
					return best != null ? Integer.toString(best.getSimulator().getEndTime()) : "-";
				}
			}
			return null;
		}
		
	}
	
	public EventSimulationSummaryViewer(EventSimulationView mainView, Composite parent, int style) {
		super(parent, style);
		this.setContentProvider(new MyContentProvider());
		this.setLabelProvider(new MyLabelProvider());
		
		this.view = mainView;
		
		//columnList = new ArrayList<TableColumn>();
		
		Table table = getTable();
		table.setLayoutData(BorderLayout.CENTER);
		table.setHeaderVisible(true);
		
		
		TableColumn column = new TableColumn(table, SWT.LEFT);
		column.setText("Solution");
		column.setWidth(150);
		
		column = new TableColumn(table, SWT.RIGHT);
		column.setText("Initial");
		column.setWidth(150);
		
		column = new TableColumn(table, SWT.RIGHT);
		column.setText("Final");
		column.setWidth(150);
		
		column = new TableColumn(table, SWT.RIGHT);
		column.setText("End Time");
		column.setWidth(150);
	}
	
	public void setInput(List<EventSimulator> result) {
		ArrayList<Object[]> res = new ArrayList<Object[]>();
		for(EventSimulator sim: result) {
			SimulatedTreeNode bestRoute = findBestRoute(sim.getRootNode());
			res.add(new Object[] {sim, bestRoute});
		}
		input = res.toArray();
		this.setInput(input);
	}
	
	private SimulatedTreeNode findBestRoute(SimulatedTreeNode rootNode) {
		SimulatedTreeNode bestLeaf = null;
		float bestScore =  Float.MAX_VALUE;
		LinkedList<SimulatedTreeNode> queue = new LinkedList<SimulatedTreeNode>();
		queue.add(rootNode);
		while (queue.size() > 0) {
			SimulatedTreeNode node = queue.poll();
			if (!node.isLeaf())
				for (SimulatedTreeNode child: node.getChildren())
					queue.add(child);
			else
				if (node.getSimulator().isCompleted()) {
					float score = getScore(node);
					if (bestLeaf == null || bestScore > score || (bestScore - score > 0.0001 
							&& bestLeaf.getSimulator().getEndTime() > node.getSimulator().getEndTime()))
					{
						bestLeaf = node;
						bestScore = score;
					}
				}
		}
		return bestLeaf;
	}

	protected float getScore(SimulatedTreeNode node) {
		if (node != null) {
			Evaluator info = view.getSelectedEvaluatorInfo();
			if (info != null) {
				EvaluatorResult evalResult = node.getEvaluatorResult(info, false);
				return evalResult.getValue(view.getSelectedEvaluatorComponent());
			}
		}
		return 0;
	}
}
